#include "game_server.h"
#include <iostream>

GameServer::GameServer(boost::asio::io_context& io_context, short port)
	: io_context_(io_context),
	acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
	next_player_id_(1) {
	std::cout << "Game server started on port: " << port << std::endl;
	start_accept();
}

void GameServer::start_accept() {
	auto session = std::make_shared<ClientSession>(
		tcp::socket(io_context_), *this);
	acceptor_.async_accept(session->socket(),
		[this, session](const boost::system::error_code& error) {
			handle_accept(session, error);
		});
}

void GameServer::handle_accept(std::shared_ptr<ClientSession> session, const boost::system::error_code& error) {
	if (!error) {
		session->start();
		join(session);
	}
	else {
		std::cerr << "Accept error: " << error.message() << std::endl;
	}
	start_accept();
}

void GameServer::join(std::shared_ptr<ClientSession> session) {
	sessions_.insert(session);
	std::cout << "Player joined. Total players: " << sessions_.size() << std::endl;
}

void GameServer::leave(std::shared_ptr<ClientSession> session) {
	if (session->get_id() != -1) {
		mcseerserver::ServerMessage msg;
		mcseerserver::PlayerLeft* left = msg.mutable_left();
		left->set_player_name(session->get_player_name());
		left->set_player_id(session->get_id());

		broadcast(msg, session);
	}

	sessions_.erase(session);
	std::cout << "Player left. Total players: " << sessions_.size() << std::endl;
}

void GameServer::broadcast(const mcseerserver::ServerMessage& msg, std::shared_ptr<ClientSession> exclude) {
	for (auto& session : sessions_) {
		if (session != exclude) {
			session->deliver(msg);
		}
	}
}